package com.ai.bitcoin.schedule.task;

import com.ai.bitcoin.constant.Bcc;
import com.ai.bitcoin.jpa.entity.BccBatch;
import com.ai.bitcoin.jpa.entity.BccPriceInfo;
import com.ai.bitcoin.jpa.entity.BccPriceInfoCrawl;
import com.ai.bitcoin.jpa.entity.BccShowControl;
import com.ai.bitcoin.jpa.service.BccBatchService;
import com.ai.bitcoin.jpa.service.BccPriceInfoCrawlService;
import com.ai.bitcoin.jpa.service.BccPriceInfoService;
import com.ai.bitcoin.jpa.service.BccShowControlService;
import com.ai.bitcoin.redis.service.BccRedisService;
import com.ai.bitcoin.serialize.BeanSerial;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author Jason
 * @date 2018/4/6
 **/
@Slf4j
@Component
public class CurrentPriceTask extends AbstractTask {
    @Autowired
    private BccPriceInfoService bccPriceInfoService;
    @Autowired
    private BccBatchService bccBatchService;
    @Autowired
    private BccPriceInfoCrawlService bccPriceInfoCrawlService;
    @Autowired
    private BccRedisService bccRedisService;
    @Autowired
    private BccShowControlService bccShowControlService;

    @Override
    public void execute() {
        long start;
        List<BccBatch> batchList;

        batchList = bccBatchService.findByBatchTypeAndBatchStateOrderByBatchTimeEndDesc(Bcc.BathType.CRAWL_PRICE_INFO, Bcc.BathState.CRAWL_DONE);
        if (batchList == null || batchList.size() == 0) {
            log.info("没有要处理的price批次");
            return;
        }
        if (batchList.size() > 1) {
            log.info("CurrentPriceTask任务好慢，错过了{}个版本了,把这些版本更新状态为:{}", batchList.size() - 1, Bcc.BathState.EXPIRE);
            for (int i = 1; i < batchList.size(); i++) {
                BccBatch bccBatch = batchList.get(i);
                bccBatch.setBatchState(Bcc.BathState.EXPIRE);
                bccBatchService.save(bccBatch);
                log.info("batchNo:{}", BeanSerial.Bean2Json(bccBatch));
            }
        }

        BccBatch latestBatch = batchList.get(0);
        String latestBathNo = latestBatch.getBatchNo();

        log.info("开始处理，batchNo:{}", BeanSerial.Bean2Json(latestBatch).toString());

        log.info("清理未发布的脏数据");
        start = System.currentTimeMillis();
        bccPriceInfoService.deleteNoPublish();
        log.info("清理未发布的脏数据，consume:{}ms", (System.currentTimeMillis() - start));

        log.info("开始将爬取的数据入库到bcc_price_info表");
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        Pageable pageable = PageRequest.of(0, pageSizeDb, sort);
        Page<BccPriceInfoCrawl> page = bccPriceInfoCrawlService.findByBatchNo(latestBathNo, pageable);
        int pageNum = page.getTotalPages();
        log.info("总共页数:{},每页大小:{}", pageNum, pageSizeDb);

        List<BccPriceInfoCrawl> list = page.getContent();
        BccShowControl bccShowControl = bccShowControlService.findByBccIdAndShowType(Bcc.BCC_DEDAULT, "price");

        for (int i = 0; i < pageNum; i++) {
            log.info("第{}页", i);
            if (i != 0) {
                page = bccPriceInfoCrawlService.findByBatchNo(latestBathNo, pageable);
                list = page.getContent();
            }
            save2PriceInfo(list, bccShowControl);
        }

        log.info("爬取的数据入库到bcc_price_info表结束，consume:{}ms", (System.currentTimeMillis() - start));

        log.info("更新批次状态,bath={},{}->{}", latestBatch, Bcc.BathState.CRAWL_DONE, Bcc.BathState.HANDLE_DONE);
        latestBatch.setBatchState(Bcc.BathState.HANDLE_DONE);
        bccBatchService.save(latestBatch);
    }

    @Transactional
    public void save2PriceInfo(List<BccPriceInfoCrawl> list, BccShowControl bccShowControl) {
        BccPriceInfo bccPriceInfo;
        for (BccPriceInfoCrawl aList : list) {
            bccPriceInfo = new BccPriceInfo();
            BeanUtils.copyProperties(aList, bccPriceInfo);
            bccPriceInfo.setRecordState(Bcc.RecordState.UN_PUBLISH);
            bccPriceInfoService.getDao().save(bccPriceInfo);
            if (StringUtils.isNotEmpty(bccPriceInfo.getPriceBtc()) && StringUtils.isNotEmpty(bccPriceInfo.getPriceUsd()) && StringUtils.isNotEmpty(bccPriceInfo.getPriceCny()))
                cachePrice2Redis(bccPriceInfo.getBccId(), getShowInfo(BeanSerial.Bean2Json(bccPriceInfo), bccShowControl));
        }
    }

    private void cachePrice2Redis(String bccId, JSONObject node) {
        //实时
        bccRedisService.cacheCurrentPrice2Redis(bccId, node);
        //天
        bccRedisService.addTodayPriceNode(bccId, node);

        bccRedisService.cache24hPrice2Redis(bccId, node);
    }

}
